/************************************************************************/
/* Name : Kiwon Yun
/* Partner's name : Eric Rooney
/* File Name : Deck.cpp
/* The name of assignment : Iteration 2
/************************************************************************/

#include "Deck.h"
#include <stdio.h>
#include <stdarg.h>

/**	 Constructor */
Deck::Deck()
{
}

/**  Destructor */
Deck::~Deck()
{
	RemoveAllCards();
}

void Deck::InitDeck( E_MODE a_mode, char* a_strTestFileName )
{
#ifdef SCORE_TEST_MODE
	readDeckFile( "scoretest.dat" );
#else
	if( a_mode == STANDARD_MODE )
	{
		// create cards in regular.
		CreateStandardDeck();

		// Randomizes the order of cards in the deck.
		shuffleDeck();
	}
	else if( a_mode == TEST_MODE )
	{
		// create cards by using deck file.
		readDeckFile( a_strTestFileName );
	}
#endif
}

void Deck::CreateStandardDeck()
{
	// Clears out the current deck
	RemoveAllCards();

	Card* pCurCard;

	// Create four kinds of card ( Clover, Heart, Diamond, Spade )
	for( int j = 0; j < 4; ++j )
	{
		char curSuit;

		switch(j) {
		case 0:
			curSuit = 'H';		// Heart
			break;
		case 1:
			curSuit = 'C';		// Clover
			break;
		case 2:
			curSuit = 'D';		// Diamond
			break;
		case 3:
			curSuit = 'S';		// Spade
			break;
		}

		// make the number cards from 2 to 10
		for( int i = 2; i < 11; ++i )
		{
			pCurCard = new Card;
			pCurCard->suit = curSuit;

			char value[3];
			sprintf( value, "%d", i );
			pCurCard->value = value;
			m_vecCard.push_back( pCurCard );
		}

		// make A card
		pCurCard = new Card;
		pCurCard->suit = curSuit;
		pCurCard->value = "A";
		m_vecCard.push_back( pCurCard );

		// make J card
		pCurCard = new Card;
		pCurCard->suit = curSuit;
		pCurCard->value = "J";
		m_vecCard.push_back( pCurCard );

		// make Q card
		pCurCard = new Card;
		pCurCard->suit = curSuit;
		pCurCard->value = "Q";
		m_vecCard.push_back( pCurCard );

		// make K card
		pCurCard = new Card;
		pCurCard->suit = curSuit;
		pCurCard->value = "K";
		m_vecCard.push_back( pCurCard );
	}

	cout << "Created to cards in deck in standard mode." << endl;
}

/*
void Deck::PrintCardsInDeck()
{
	FILE* pFile = NULL;
	fopen_s( &pFile, "log.txt", "a" );

	vector <Card*>::iterator it;
	for ( it = m_vecCard.begin(); it != m_vecCard.end( ) ; ++it )
	{
		Card* pCard;
		pCard = (*it);

		char log[1024];
		sprintf( log, "%c%s\r", pCard->suit, pCard->value.c_str() );

		if( pFile )
		{
			fprintf_s( pFile, log );
		}
	}

	if( pFile )
	{
		fclose( pFile );
		pFile = NULL;
	}
}
*/

/** Randomizes the order of cards in the deck. */
void Deck::shuffleDeck()
{
	random_shuffle( m_vecCard.begin(), m_vecCard.end() );
/*
	cout << "shuffleDeck() Result : " << endl;
	vector <Card>::iterator it;
	for ( it = m_vecCard.begin(); it != m_vecCard.end( ) ; ++it )
	{
		Card tempCard;
		tempCard = (*it);
		cout << tempCard.suit << " - " << tempCard.value << endl;
	}
*/
}

/** Draws a card from the deck, removing the card from the deck. 
* The return value is the card drawn. Note that the result is undefined 
* when the deck is empty.*/
Card* Deck::RequestCard()
{
	if( m_vecCard.size() == 0 )
	{
		cout << "You can't draw cards because the deck is empty!" << endl;
		return NULL;
	}

	Card* pTopCard = m_vecCard.back();
	m_vecCard.pop_back();

	return pTopCard;
}

/** Returns the number of cards remaining in the deck. */
int Deck::getSize() const
{
	return (int)m_vecCard.size();
}

/** Clears out the current deck and reads in a new deck from a file, where 
* the format is:
* 
* $(SUIT)$(VALUE)
* 
* Example:
* 
* D10
* C4
* HA
* 
* ...etc. Note that the cards are ordered such that the first card read is
* at the bottom of the deck and the last is at the top of the deck, and the
* first to be dealt.*/
void Deck::readDeckFile(string a_strFilename)
{
	string filename = a_strFilename;

	// Clears out the current deck
	RemoveAllCards();
	
	const char* strFileName = filename.c_str();

	// open destination file
	ifstream inf;
	inf.open( strFileName, ios_base::in );
	if(!inf.is_open()){
		cout << "ERROR : Cannot open file : " << strFileName << endl;
		exit(1);
	}

	string line;

	// read for each line
	while ( getline( inf, line ) )
	{
		if (line != "")
		{
			// the first character means the suit of card
			// the remaining character means the value of card
			string strValue;

			// get the remaining character excepted for the first character
			strValue.assign( line.c_str(), 1, line.length() );		

			Card* pOneCard = new Card;
			pOneCard->suit = line[0];		// get the first character
			pOneCard->value = strValue;	
			m_vecCard.push_back( pOneCard );
		}
	}

	inf.close();

	cout << "Created to cards in deck in test mode. (from " << strFileName << ")" << endl;

/*
	cout << "Read File Result : " << endl;
	vector <Card>::iterator it;
	for ( it = m_vecCard.begin(); it != m_vecCard.end( ) ; it++ )
	{
		Card tempCard;
		tempCard = (*it);
		cout << tempCard.suit << " - " << tempCard.value << endl;
	}
*/
}

void Deck::RemoveAllCards()
{
	vector <Card*>::iterator it;
	for ( it = m_vecCard.begin(); it != m_vecCard.end( ) ; ++it )
	{
		Card* pCard;
		pCard = (*it);

		if( pCard != NULL )
		{
			delete pCard;
			pCard = NULL;
		}
	}

	m_vecCard.clear();
}
